﻿// Session.cpp: implementation of the CSession class.
//
//////////////////////////////////////////////////////////////////////


#include "CSession.h"
#include "parasolid_kernel.h"
#include "frustrum_ifails.h"

#include <assert.h>
#include <stdio.h>

//#ifdef _DEBUG
//#undef THIS_FILE
//static char THIS_FILE[]=__FILE__;
//#define new DEBUG_NEW
//#endif

// The following are frustrum function declarations

extern void StartFileFrustrum(int *);
extern void AbortFrustrum(int *);
extern void StopFileFrustrum(int *);
extern void OpenReadFrustrumFile(const int *, const int *, const char *, const int *,
	const int *, int *, int *);
extern void OpenWriteFrustrumFile(const int *, const int *, const char *, const int *,
	const char *, const int *, int *, int *);
extern void CloseFrustrumFile(const int *, const int *, const int *, int *);
extern void ReadFromFrustrumFile(const int *, const int *, const int *, char *, int *,
	int *);
extern void WriteToFrustrumFile(const int *, const int *, const int *, const char *,
	int *);
extern int SeekXT(const int, const int, unsigned int, unsigned int);


extern "C" {
	PK_ERROR_code_t FRU_delta_open_for_write(PK_PMARK_t, PK_DELTA_t *);
	PK_ERROR_code_t FRU_delta_open_for_read(PK_DELTA_t);
	PK_ERROR_code_t FRU_delta_write(PK_DELTA_t, unsigned, const char *);
	PK_ERROR_code_t FRU_delta_read(PK_DELTA_t, unsigned, char *);
	PK_ERROR_code_t FRU_delta_delete(PK_DELTA_t);
	PK_ERROR_code_t FRU_delta_close(PK_DELTA_t);
	int FRU__delta_init(int action);
}

CSession::CSession()
{
	// Start up Parasolid
	if (!Start()) assert(0);
}

CSession::~CSession()
{
	// Close down Parasolid
	Stop();
}


bool CSession::Start()
{
	bool ok = true;

	// Register frustrum functions
	// Note: the GO functions are registered in CExampleAppDoc

	PK_FSTART_f_t sf = StartFrustrum;
	PK_FABORT_f_t af = AbortFrustrum;
	PK_FSTOP_f_t stf = StopFrustrum;
	PK_FMALLO_f_t gm = GetMemory;
	PK_FMFREE_f_t rm = ReturnMemory;
	PK_FFOPRD_f_t orf = OpenReadFrustrumFile;
	PK_FFOPWR_f_t ow = OpenWriteFrustrumFile;
	PK_FFCLOS_f_t cf = CloseFrustrumFile;
	PK_FFREAD_f_t rf = ReadFromFrustrumFile;
	PK_FFWRIT_f_t wf = WriteToFrustrumFile;
	PK_FFSKXT_f_t sk = SeekXT;

	PK_SESSION_register_fru_o_t fru_opts;
	PK_SESSION_register_fru_o_m(fru_opts);

	fru_opts.fstart = &sf;
	//fru_opts.fabort = &af;
	fru_opts.fstop = &stf;
	fru_opts.fmallo = &gm;
	fru_opts.fmfree = &rm;
	fru_opts.ffoprd = &orf;
	fru_opts.ffopwr = &ow;
	fru_opts.ffclos = &cf;
	fru_opts.ffread = &rf;
	fru_opts.ffwrit = &wf;
	//fru_opts.ffskxt = &sk;

	assert(PK_SESSION_register_fru_2(&fru_opts) == PK_ERROR_no_errors);

	// Register Delta Frustrum

	PK_DELTA_frustrum_t delta_fru;

	delta_fru.open_for_write_fn = FRU_delta_open_for_write;
	delta_fru.open_for_read_fn = FRU_delta_open_for_read;
	delta_fru.close_fn = FRU_delta_close;
	delta_fru.write_fn = FRU_delta_write;
	delta_fru.read_fn = FRU_delta_read;
	delta_fru.delete_fn = FRU_delta_delete;

	assert(PK_DELTA_register_callbacks(delta_fru) == PK_ERROR_no_errors);

	// Register Error Handler
	PK_ERROR_frustrum_t errorFru;
	errorFru.handler_fn = PKerrorHandler;
	assert(PK_ERROR_register_callbacks(errorFru) == PK_ERROR_no_errors);

	// Starts the modeller

	PK_SESSION_start_o_t options;
	PK_SESSION_start_o_m(options);


	PK_SESSION_start(&options);

	// Check to see if it all started up OK
	PK_LOGICAL_t was_error = PK_LOGICAL_true;
	PK_ERROR_sf_t error_sf;
	PK_ERROR_ask_last(&was_error, &error_sf);
	if (was_error)
		return false;

	// Enable latest behaviour
	PK_SESSION_behaviour_t behaviour_requested;
	behaviour_requested.behaviour_type = PK_SESSION_behave_as_latest_c;
	behaviour_requested.behaviour_value = 0;
	PK_SESSION_set_behaviour_o_t behaviour_opts;
	PK_SESSION_set_behaviour_o_m(behaviour_opts);
	PK_SESSION_behaviour_t behaviour_set;
	PK_SESSION_behaviour_t behaviour_previous;
	PK_behaviour_status_t behaviour_status;
	PK_SESSION_set_behaviour(behaviour_requested, &behaviour_opts, &behaviour_set, &behaviour_previous, &behaviour_status);


	return ok;
}

bool CSession::Stop()
{
	PK_SESSION_stop();
	return true;
}

void CSession::StartFrustrum(int * ifail)
{
	*ifail = FR_no_errors;
	FRU__delta_init(1);
	StartFileFrustrum(ifail);
}

void CSession::StopFrustrum(int * ifail)
{

	*ifail = FR_no_errors;
	FRU__delta_init(2);
	StopFileFrustrum(ifail);
}

void CSession::GetMemory(int * nBytes, char * * memory, int * ifail)
{

	*memory = new char[*nBytes];
	*ifail = (*memory) ? FR_no_errors : FR_memory_full;
}

void CSession::ReturnMemory(int * nBytes, char * * memory, int * ifail)
{
	delete[] * memory;
	*ifail = FR_no_errors;
}

PK_ERROR_code_t CSession::PKerrorHandler(PK_ERROR_sf_t* error)
{
	char text[500];
	snprintf(text, 500, "PK error: %s returned %s.", error->function,
		error->code_token);
	//AfxMessageBox(CString(text));
	printf(text);
	return error->code;
}
